package fr.ensai.lignededix.bd;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import fr.ensai.lignededix.exceptions.FonctionalException;
import fr.ensai.lignededix.exceptions.TechnicalException;
import fr.ensai.lignededix.metier.joueur.Utilisateur;
import fr.ensai.lignededix.metier.partie.Partie;

public class UtilisateurDAO extends DAO<Utilisateur>{

	
	@Override
	public int create(Utilisateur obj) throws FonctionalException {

		int idUtilisateur=-1;

		try{	

			//Etablissement de la connection

			Statement instruction = connect.createStatement();


			ResultSet resultat= instruction.executeQuery("SELECT seqUtilisateur.nextval from dual");
			resultat.next();
			idUtilisateur=resultat.getInt(1);

			instruction.executeUpdate("INSERT INTO UTILISATEUR (idUtilisateur, login, motDePasse) VALUES " +
					"("+idUtilisateur+", '"+obj.getIdentifiant()+"','"+obj.getMotDePasse()+"')");

			//Fermeture de l'instruction
			instruction.close();


		}
		catch (SQLException e){
			throw new FonctionalException("Une erreur est survenue, la création de l'utilisateur a échouée.");
		}
		return idUtilisateur;

	}



	public boolean isPseudoValide(String pseudo) throws FonctionalException, TechnicalException{


		boolean valide=false;
		int idUtilisateur=-1;

		try{	
			//Etablissement de la connection
			Statement instruction = connect.createStatement();
			ResultSet resultat = instruction.executeQuery("SELECT * FROM UTILISATEUR where (login='"+pseudo+"')");

			while(resultat.next()){
				idUtilisateur = resultat.getInt(1);
			}

			if (idUtilisateur==-1) {
				valide=true;
			}

			//Fermeture de l'instruction
			instruction.close();



		}
		catch (SQLException e){
			throw new FonctionalException("Une erreur est survenue, la création de l'utilisateur a échouée.");
		}
		catch(NullPointerException npe){
			throw new TechnicalException("Une erreur technique s'est produite");
		}

		return valide;
	}


	public int authentifier(String pseudo, String mdp) throws FonctionalException, TechnicalException {


		int idUtilisateur=-1;


		try{	
			//Etablissement de la connection
			Statement instruction = connect.createStatement();
			ResultSet resultat = instruction.executeQuery("SELECT * FROM UTILISATEUR where login='"+pseudo+"' and motDePasse='"+mdp+"'");

			while(resultat.next()){

				idUtilisateur = resultat.getInt("idUtilisateur");

			}


			//Fermeture de l'instruction
			instruction.close();



		}
		catch (SQLException e){
			throw new FonctionalException("Une erreur est survenue, l'authentification de l'utilisateur n'a pas pu être effectuée.");
		}
		catch(NullPointerException npe){
			throw new TechnicalException("Une erreur technique s'est produite.");
		}

		return idUtilisateur;
	}


	public String calculerDesStatistiques(Utilisateur jj) throws FonctionalException{

		int nbPartie=-1;
		int nbGagnee=-1;
		int nbEgalite=-1;
		int scoreMaxJoueur=0;
		int scoreMinJoueur=-1;
		int scoreMax=0;
		int scoreMin=-1;
		int uti=jj.getNumUtilisateur();
		try{

			Statement instruction = connect.createStatement();


			//on a le nombre de partie pour les parties finies
			ResultSet resultat1=instruction.executeQuery("SELECT count(*) FROM PARTIE where ("+uti+"=idUtilisateur1 or "+uti+"=idUtilisateur2) and datefin is not NULL");
			resultat1.next();
			nbPartie=resultat1.getInt(1);

			//on a le nombre de partie gagnee les parties finies
			ResultSet resultat2=instruction.executeQuery("SELECT count(*) FROM PARTIE where (("+uti+"=idUtilisateur1 and score1>score2) or ("+uti+"=idUtilisateur2 and score2>score1)) and datefin is not NULL");
			resultat2.next();
			nbGagnee=resultat2.getInt(1);

			//on a le nombre de match nul les parties finies
			ResultSet resultat3=instruction.executeQuery("SELECT count(*) FROM PARTIE where ("+uti+"=idUtilisateur1  or "+uti+"=idUtilisateur2) and score2=score1 and datefin is not NULL");
			resultat3.next();
			nbEgalite=resultat3.getInt(1);

			//on reccupére tout les scores du joueur
			ResultSet resultat4=instruction.executeQuery("SELECT score1 From PARTIE where "+uti+"=idUtilisateur1 and datefin is not NULL"); 
			while(resultat4.next()){			


				if(resultat4.getInt(1)>scoreMaxJoueur){
					scoreMaxJoueur=resultat4.getInt(1);
				}
				if(resultat4.getInt(1)<scoreMinJoueur || scoreMin==-1){
					scoreMinJoueur=resultat4.getInt(1);
				}

			}
			ResultSet resultat5=instruction.executeQuery("SELECT score2 From PARTIE where "+uti+"=idUtilisateur2 and datefin is not NULL"); 

			while(resultat5.next()){			


				if(resultat5.getInt(1)>scoreMaxJoueur){
					scoreMaxJoueur=resultat5.getInt(1);
				}
				if(resultat5.getInt(1)<scoreMinJoueur || scoreMinJoueur==-1){
					scoreMinJoueur=resultat5.getInt(1);
				}

			}



			//on reccupére tout les scores
			ResultSet resultat6=instruction.executeQuery("SELECT score1, score2 From PARTIE where datefin is not NULL"); 
			ResultSetMetaData resultat6Meta = resultat6.getMetaData();	
			while(resultat6.next()){			
				for(int i = 1; i <=  resultat6Meta.getColumnCount(); i++){ //ici on a normalement 2 colones
					if(resultat6.getInt(i)>scoreMax){
						scoreMax=resultat6.getInt(i);
					}
					if(resultat6.getInt(i)<scoreMin || scoreMin==-1){
						scoreMin=resultat6.getInt(i);
					}
				}
			}


			//Fermeture de l'instruction
			instruction.close();
			if(scoreMinJoueur==-1){
				scoreMinJoueur=0;
			}

		}
		catch (SQLException e){
			throw new FonctionalException("Une erreur s'est produite");
		}


		return "Le joueur "+jj.getIdentifiant()+" a joué "+nbPartie+" partie(s) dont "+nbGagnee+" gagnée(s) et "+nbEgalite+" partie(s) nulle(s). \n" +
		"Son score maximum est de "+scoreMaxJoueur+" et son score minimum est de "+scoreMinJoueur+". \n" +
		"Le score maximum sur l'ensemble des joueurs est de "+scoreMax+" et le score minimum sur l'ensemble des joueurs est de "+scoreMin+". \n";

	}



	@Override
	public List<Utilisateur> obtenirListeAttente(Utilisateur obj) throws FonctionalException {

		List<Utilisateur> listeUtilisateur=new ArrayList<Utilisateur>();
		try {
			Statement instruction = connect.createStatement();
			
			ResultSet resultat=instruction.executeQuery("SELECT * from UTILISATEUR where adresseIp is NOT NULL AND idUtilisateur!='"+obj.getNumUtilisateur()+"'");
			
			while (resultat.next()) {
				Utilisateur u=new Utilisateur(resultat.getInt("idUtilisateur"), resultat.getString("login"),
						resultat.getString("motDePasse"),resultat.getString("listeTaillesVoulues"),
						resultat.getString("adresseIp"));
				listeUtilisateur.add(u);
			}
			
			
		} catch (Exception e) {
			throw new FonctionalException("L'obtention de la liste d'attente a échouée.");
		}
		
		
		return listeUtilisateur;
	}

	@Override
	public void sinscrireSurListeAttente(Utilisateur obj) throws FonctionalException {
		try {
			Statement instruction = connect.createStatement();
			
			instruction.executeUpdate("UPDATE UTILISATEUR SET adresseIp='"+obj.getAdresseIp()+"'," +
					" listeTaillesVoulues='"+obj.getTaillesDeGrilleVoulues()+"'" +
					" where idUtilisateur="+obj.getNumUtilisateur()+"");
			
			
			
		} catch (Exception e) {
			throw new FonctionalException("L'inscription sur la liste d'attente a échoué.");
		}
		
	}
	
	public void desinscrireListeAttente(Utilisateur obj) throws FonctionalException {
		try {
			Statement instruction = connect.createStatement();
			
			instruction.executeUpdate("UPDATE UTILISATEUR SET adresseIp=null, listeTaillesVoulues=null where idUtilisateur="+obj.getNumUtilisateur()+"");
			
			
			
		} catch (Exception e) {
			throw new FonctionalException("La désinscription sur la liste d'attente a échoué.");
		}
		
	}
	
	@Override
	public Utilisateur update(Utilisateur obj) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void delete(Utilisateur obj) {
		throw new UnsupportedOperationException();

	}
	
	
	@Override
	public void executerRequete(String ligne) {
		throw new UnsupportedOperationException();

	}

	@Override
	public void updateDateFin(Utilisateur obj) {
		throw new UnsupportedOperationException();

	}


	@Override
	public List<Utilisateur> getAll(int idUtilisateur1, int idUtilisateur2) {
		throw new UnsupportedOperationException();
	}


	@Override
	public void updateScore(Partie partieInterrompueOuFinie)
			throws FonctionalException {
		throw new UnsupportedOperationException();
		
	}
	
	@Override
	public Utilisateur find(int id) throws FonctionalException {
		throw new UnsupportedOperationException();
	}

	//Constructeur

	public UtilisateurDAO(Connection connect){
		this.connect=connect;
	}



	




	

	







}
